//var Util = require('../Util/Util').Util;
var Animation = require('../Animation').Animation;
//var Scale = require('../Util/Scaler').Scale;

exports.PagedBrowserOptions = Core.Class.subclass ({
/** @lends Browser.PagedBrowserOptions.prototype */
	
	classname: 'PagedBrowserOptions',
	
	/**
	 * @class Options for the page browser
	 * Parameters include blocksPerPage, topMargin, browserSize, origin
	 * 
	 * @constructs The default constructor.
	 * @augments Core.Class
	 */
	initialize: function() {
		this.blocksPerPage = 4;
		this.topMargin = 0;
		this.browserSize = null;//new Core.Size(Math.max(Core.Capabilities.getScreenHeight(), Core.Capabilities.getScreenWidth()),Math.min(Core.Capabilities.getScreenHeight(), Core.Capabilities.getScreenWidth()));//Util.screenSize(true);
		this.origin = new Core.Vector(0,0);
	},
	
});

exports.PagedBrowser = Animation.AANode.subclass ({
/** @lends Browser.PagedBrowser.prototype */
	
	classname: 'PagedBrowser',
	
	/** 
	 * Enumeration for PagedBrowser states
	 * @namespace
	 */
	State: {
		/** Idle */
		Idle: 0,
		/** Swiping in the Browser */
		Swiping: 1,
	},
	
	/**
	 * @class A swipable browser that is paged and can have a page indicator attached to it.
	 * @param {Core.Size} blockSize The size for each block in the browser
	 * @param {Array} blocks The blocks for the browser
	 * @param {Browser.PagedBrowserOptions} options The browser options
	 * @constructs The default constructor.
	 * @augments Animation.AANode
	 */
	initialize: function(blockSize, blocks, options, callback,activeBlockIndex) {
		var self = this;
		this.state = this.State.Idle;
		this.activePage = 0;
		this.blockSize = blockSize;
		this.blocks = blocks;
		this.options = options;
		this._callback = callback;
		this.updateNumberOfPages();
        this._activeBlock = blocks[activeBlockIndex];
		
		this.setPosition(this.options.origin.clone());
		
		this.touchTarget = new GL2.TouchTarget();
		this.touchTarget.setSize(this.options.browserSize);
		this.touchTarget.setAnchor(new Core.Point(0,0));
		this.touchTarget.setPosition(this.getPosition().clone());
		
		this.scrollTouchHandler = new this.BrowserScrollTouchHandler(this);
		this.touchTarget.getTouchEmitter().addListener(this.scrollTouchHandler, this.scrollTouchHandler.onTouch);
		
		this.initializeBlocks();
	},
	
	/**
	 * Gets the touch target for this browser
	 * @returns {GL2.TouchTarget} The touch target
	 */
	getTouchTarget: function(){
        return this.touchTarget;
    },
	
	/**
	 * Set the page indicator for this browser.
	 * The indicator should implement setMaxPages and setCurrentPage
	 * @param {Object} pi The page indicator
	 */
	setPageIndicator: function(pi) {
		
		this.pageIndicator = pi;
		this.pageIndicator.setMaxPages(this.numPages);
		this.pageIndicator.setCurrentPage(this.activePage + 1);
	},

	/**
	 * Set the page action for this browser.
	 * @param {Object} pi The page indicator
	 */
	setPageAction: function(pa) {
		
		this.pageAction = pa;
	},
	
	/**
	 * Updates the number of pages for this browser
	 * @private
	 */
	updateNumberOfPages: function() {
		
		if (!this.blocks || this.blocks.length == 0)
			this.numPages = 1;
		else {
			this.numPages = Math.floor(this.blocks.length / this.options.blocksPerPage);
			if ((this.blocks.length % this.options.blocksPerPage) != 0)
				this.numPages++;
		}
	},
	
	/**
	 * Goes through each block and places them appropriately in each page of the browser
	 * @private
	 */
	initializeBlocks: function() {
		
		this.currentPopulatePage = 0;
		this.currentPopulateBlock = 0;
		
		var browserSize = this.options.browserSize;
		
		var columns = Math.floor(browserSize.getWidth() / this.blockSize.getWidth());
		var rows = Math.floor(browserSize.getHeight() / this.blockSize.getHeight());
		
		var xPixels = browserSize.getWidth() / columns;
		var yPixels = (browserSize.getHeight() - this.options.topMargin) / rows;
		
		var xOffset = xPixels / 2;
		var yOffset = yPixels / 2;
		
		if (!this.blocks) return;
		for (var i in this.blocks) {
			var block = this.blocks[i];
			
			this.currentPopulatePage = Math.floor(this.currentPopulateBlock / this.options.blocksPerPage);
			
			var currentBlockOnThisPage = this.currentPopulateBlock % this.options.blocksPerPage;
			
			var row = Math.floor(currentBlockOnThisPage / columns);
			var column = currentBlockOnThisPage % columns;
			
			var xPos = browserSize.getWidth() * this.currentPopulatePage + (column*xPixels + xOffset);
			var yPos = browserSize.getHeight() - ((rows-1-row) * yPixels + yOffset - this.options.topMargin);
			
			//NgLogD('' + xPos + ', ' + yPos);
			
			block.setPosition(xPos, yPos);
			this.currentPopulateBlock++;
			
			this.addChild(block);
		}
	},
	
	

	/**
	 * Adds a block to the end position of this browser
	 * @param {Object} block The block to add
	 */
	addBlock: function(block) {
		
		var browserSize = this.options.browserSize;
		
		var columns = Math.floor(browserSize.getWidth() / this.blockSize.getWidth());
		var rows = Math.floor(browserSize.getHeight() / this.blockSize.getHeight());
		
		var xPixels = browserSize.getWidth() / columns;
		var yPixels = (browserSize.getHeight() - this.options.topMargin) / rows;
		
		var xOffset = xPixels / 2;
		var yOffset = yPixels / 2;
		
		this.currentPopulatePage = Math.floor(this.currentPopulateBlock / this.options.blocksPerPage);
		
		var currentBlockOnThisPage = this.currentPopulateBlock % this.options.blocksPerPage;
		
		var row = Math.floor(currentBlockOnThisPage / columns);
		var column = currentBlockOnThisPage % columns;
		
		var xPos = browserSize.getWidth() * this.currentPopulatePage + (column*xPixels + xOffset);
		var yPos = (rows-1-row) * yPixels + yOffset - this.options.topMargin;
			
		block.setPosition(xPos, yPos);
		this.currentPopulateBlock++;
			
		this.addChild(block);
		this.blocks.push(block);
		
		this.updateOnAddRemoveBlock();
	},
	
	/**
	 * Removes a single block from this browser
	 * @param {Object} removeBlock
	 */
	removeBlock: function(removeBlock) {
		
		var array = [];
		array.push(removeBlock);
		this.removeBlocks(array);
	},
	
	/**
	 * Removes multiple blocks from this browser and reorganizes all block positions
	 * @param {Array} removeBlocks
	 */
	removeBlocks: function(removeBlocks) {
		
		if (!removeBlocks || removeBlocks.length == 0) return;
		
		for (var i in removeBlocks) {
			
			var removeBlock = removeBlocks[i];
			this.removeChild(removeBlock);
			//Util.removeByValue(this.blocks, removeBlock);
			var index = this.blocks.indexOf(removeBlock);
			if(index >= 0)
			{
				this.blocks.splice(index,1);
			}
			
		}
		
		for (var i in this.blocks) {
			this.removeChild(this.blocks[i]);
		}
		
		this.initializeBlocks();
		this.updateOnAddRemoveBlock();
		
		if (this.activePage == this.numPages && this.numPages > 0)
			this.slideToPage(this.activePage - 1);
	},
	
	getBlocks: function() {
		return this.blocks;
	},
	
	/**
	 * Performs internal data updates when blocks have been removed or added to the Browser
	 * @private
	 */
	updateOnAddRemoveBlock: function() {
		
		//this.updateNumberOfPages();
		
		if (this.pageIndicator) {
			
			this.pageIndicator.setMaxPages(this.numPages);
			this.pageIndicator.setCurrentPage(this.activePage + 1);
		}
		
		// TODO: Update browser size
	},
    jumpToPage: function(page) {
        
        NgLogD("Sliding To Page " + page);
        if(this._callback && (page < 0 || page>this.numPages-1) ){
            return;
        }
        var slidePos = new Core.Vector(this.options.browserSize.getWidth() * page * -1 + this.options.origin.getX(), this.getPosition().getY());
        NgLogD("Slide Position " + slidePos.getX() + ", " + slidePos.getY());
        var slideAction = new Animation.AAMoveTo(slidePos, 0.001);
        var slideActionEase = new Animation.AAEaseOut(slideAction, 2);
        
        var thisBrowser = this;
        var callback = new Animation.AACallFuncND(function() { thisBrowser.onSlidToPage(page) });
        
        this.runAction(new Animation.AASequence(slideAction, callback));
    },
	
	/**
	 * Animates a change to the specified page
	 * @param {int} page The page to slide to
	 */
	slideToPage: function(page) {
		
		NgLogD("Sliding To Page " + page);
		if(this._callback && (page < 0 || page>this.numPages-1) ){
 			return;
 		}
		var slidePos = new Core.Vector(this.options.browserSize.getWidth() * page * -1 + this.options.origin.getX(), this.getPosition().getY());
		NgLogD("Slide Position " + slidePos.getX() + ", " + slidePos.getY());
		var slideAction = new Animation.AAMoveTo(slidePos, 0.3);
		var slideActionEase = new Animation.AAEaseOut(slideAction, 2);
		
		var thisBrowser = this;
		var callback = new Animation.AACallFuncND(function() { thisBrowser.onSlidToPage(page) });
		
		this.runAction(new Animation.AASequence(slideAction, callback));
	},
	
	/**
	 * Callback when slideToPage animation has completed
	 * @private
	 * @param {Object} page The page slid to
	 */
	onSlidToPage: function(page) {
		
		NgLogD("On Slid To Page " + page);
		
		this.activePage = page;
		this.state = this.State.Idle;
 		if(this._callback){
 			this._callback(this.activePage);
 		}
 		if (this.pageIndicator) {
			this.pageIndicator.setCurrentPage(this.activePage + 1);
		}
 		if (this.pageAction) {
			this.pageAction.setHighlighted(this.activePage);
		}

	},
	
	destroy: function($super) {
		
		for (var i = this._children.length - 1; i >= 0; i--) {
			this._children[i].destroy();
		}
		$super();
	},
	
	$BrowserScrollTouchHandler: Core.MessageListener.subclass({
		
		initialize: function(browser) {
			
			this._browser = browser;
			this._target = browser.getTouchTarget();
            this._blockePressed = null;
            
		},
		
		onTouch: function(touch) {
			
			switch (touch.getAction()) {
				
				case touch.Action.Start:
					
					
//					if (this._trackingId != touch.getId()) {
//						this._previoustouchedBlock = this._touchedBlock;
//					}
//					else this._previoustouchedBlock = null;
                    this._trackingId = touch.getId();
                    if(this._blockePressed){
                        this._blockePressed.inactivate();
                    }                                          
                    for (var i = 0; i < this._browser.blocks.length; i++) {
                        if (this._browser.blocks[i].getTouchTarget &&
                            touch.getIsInside(this._browser.blocks[i].getTouchTarget())) {
                            if (typeof this._browser.blocks[i].blockPressed != 'undefined' && this._browser._activeBlock != this._browser.blocks[i]) 
                            { 
//                                if(this._blockePressed){
//                                    this._blockePressed.inactivate();
//                                }
                                this._browser.blocks[i].blockPressed();
                                this._blockePressed = this._browser.blocks[i];
                                break;
                               // this._browser.blocks[i].touchedBlock(); 
                            }
                        }
                    }
					
					//this._trackingId = touch.getId();
					this._trackingCurrent = touch.getPosition();
					this._swipeStartX = touch.getPosition().getX();
					
					this._browser.stopAllActions();
				
					var local = this._browser.getParent().screenToLocal(this._trackingCurrent);
                    var current = this._browser.getPosition();
                    
                    this._originalPosition = this._browser.getPosition().clone();
                    
                    //offset of the actual difference between the point of touch and the current position of tilemap
                    this._trackingOffset = new Core.Vector(current.getX() - local.getX(), current.getY() - local.getY());
				
					return true;
				case touch.Action.End:
				
//					if (this._trackingId != touch.getId()) 
//					{
//						if (this._previoustouchedBlock)
//							this._previoustouchedBlock.inactivate();
//                        return;
//					}
					
					//this._trackingId = NaN;
				
					var state = this._browser.state;
					if (state == this._browser.State.Idle) {
						for (var i = 0; i < this._browser.blocks.length; i++) {
							if (this._browser.blocks[i].getTouchTarget &&
								touch.getIsInside(this._browser.blocks[i].getTouchTarget())) {
								if (typeof this._browser.blocks[i].touchedBlock != 'undefined' && this._browser.blocks[i] != this._browser._activeBlock) 
                                {
                                    if (typeof this._browser._activeBlock.inactivate != 'undefined') 
                                    {
                                        this._browser._activeBlock.inactivate();
                                    }
                                    this._blockePressed = null;
                                    this._browser.blocks[i].touchedBlock(); 
                                    this._browser._activeBlock = this._browser.blocks[i];
                                }
							}//else{
                                if(this._browser.blocks[i]._isPressed){
                                    this._browser.blocks[i].inactivate();
                              //  }
                            }
						}
						
					}
					
					if (state == this._browser.State.Swiping) {
						
						var activePage = this._browser.activePage;
						var numPages = this._browser.numPages;
						var swipeDistance = touch.getPosition().getX() - this._swipeStartX;
						
						if (swipeDistance > GACommonUtils.adjustWidthWithDevice(50)) {
							
							if (activePage == 0)
								this._browser.slideToPage(activePage);
							else
								this._browser.slideToPage(activePage-1);
						}
						else if (swipeDistance < GACommonUtils.adjustWidthWithDevice(-50)) {
							
							if (activePage == numPages - 1)
								this._browser.slideToPage(activePage);
							else
								this._browser.slideToPage(activePage+1);
						}
						else {
							this._browser.slideToPage(this._browser.activePage);
						}
					}
				
					break;
				case touch.Action.Move:
				
					
//					if (this._trackingId != touch.getId()) 
//					{
//						if (this._previoustouchedBlock)
//							this._previoustouchedBlock.inactivate();
//                        return;
//					}
					
					var xChange = Math.abs(this._trackingCurrent.getX() - touch.getPosition().getX());
                    if (xChange < GACommonUtils.adjustWidthWithDevice(10)) {
                        return;
                    }
                    if(this._blockePressed && this._trackingId == touch.getId())
                    {
                        if (typeof this._blockePressed.inactivate != 'undefined') 
                        {
                            this._blockePressed.inactivate();
                        }
                        this._blockePressed = null;
                    }
					
					this._browser.state = this._browser.State.Swiping;
					
					//if it moved kill the touchedobject
					this._touchedBlock = null;
				
					this._trackingCurrent = touch.getPosition();
					var current = this._browser.getParent().screenToLocal(this._trackingCurrent);
                    var offset = this._trackingOffset;
					
					var tot = current.getX() + offset.getX();

					if(this._browser._callback!=null && ((current.getX() + offset.getX())>0)){
	 					return;
					}else if(this._browser._callback!=null && ((current.getX() + offset.getX())<-(Core.Capabilities.getScreenHeight()*(this._browser.numPages-1)))){
						return;
					}
					
					var newPosition = new Core.Vector(current.getX() + offset.getX(), this._browser.getPosition().getY());
					this._browser.setPosition(newPosition);
					break;
			}
			
		},
	}),
});
